/**
 * Copyright 2005 SIB Framework

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */

package org.sibframework.sda;

import java.lang.reflect.Field;

import org.sibframework.sda.annotation.Column;
import org.sibframework.sda.annotation.Table;
import org.sibframework.utils.Naming;

/**
 * A intelligent Table Provider, automatic guess the table name of a Class, also the columns
 * @author Spring Song
 *
 */
public class IntelligentTableProvider implements TableProvider {
	
	private static final String DEFAULT_PK_NAME = "id"; 
	
	private Class<Object> entityClass = null;
	private String tableName = null;
	private String pkName = null;
	
	/**
	 * Initial the table provider use a class;
	 * @param clazz
	 */
	public IntelligentTableProvider(Class<Object> clazz) {
		assert clazz != null;
		if (clazz == null) {
			throw new NullPointerException();
		}
		this.entityClass = clazz;
		Table tableAnnotation = this.entityClass.getAnnotation(Table.class);
		if (tableAnnotation != null && tableAnnotation.tableName() != null && tableAnnotation.tableName().length() > 0) {
			this.tableName = tableAnnotation.tableName();
		} else {
			Naming tableNaming = Naming.createByFieldName(this.entityClass.getSimpleName());
			this.tableName = tableNaming.getSqlname();
		}

		//field with annotation
		for (Field field : this.entityClass.getDeclaredFields()) {
			Column colan = field.getAnnotation(Column.class);
			if ((colan != null && colan.isPrimaryKey())) {
				Naming pkNaming = Naming.createByFieldName(field.getName());
				this.pkName = pkNaming.getSqlname();
				return;
			}
		}
		
		//field is "id" or table name + "id";
		for (Field field : this.entityClass.getDeclaredFields()) {
			if (field.getName().equalsIgnoreCase(DEFAULT_PK_NAME) || field.getName().equalsIgnoreCase(this.entityClass.getSimpleName() + DEFAULT_PK_NAME)) {
				Naming pkNaming = Naming.createByFieldName(field.getName());
				this.pkName = pkNaming.getSqlname();
				return;
			}
		}
		
		//field contains "id";
		for (Field field : this.entityClass.getDeclaredFields()) {
			if (field.getName().toUpperCase().contains("ID")) {
				Naming pkNaming = Naming.createByFieldName(field.getName());
				this.pkName = pkNaming.getSqlname();
				return;
			}
		}
		//assert this.pkName != null;
		if (this.pkName == null) {
			System.err.println(this.entityClass.getName() + " reflect exception: IntelligentTableProvider can't find primary key field.");
		}
	}
	
	/* (non-Javadoc)
	 * @see org.sibframework.sda.TableProvider#getTableName()
	 */
	@Override
	public String getTableName() {
		return tableName;
	}

	@Override
	public String getPrimaryKey() {
		return pkName;
	}


	public Class<Object> getEntityClass() {
		return entityClass;
	}

}
